/*
Copyright 2007 Nathan Baker

This file is part of XAliens.

XAliens is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

XAliens is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with XAliens.  If not, see <http://www.gnu.org/licenses/>.
 */

package sprites;

import exceptions.ImageNotLoadedException;
import utils.BoundsRect;

import java.awt.*;
import java.awt.image.BufferedImage;

public class Entity extends Sprite {
    protected Integer mVelocityX, mVelocityY;
    protected BoundsRect mBounds; // used to determine the area which the Entity cannot leave

    /**
     * Creates a default Entity.
     */
    protected Entity() {
        // nothing to see here...
    }

    /**
     * Creates an Entity with an image.
     *
     * @param img The image to load from.
     */
    protected Entity(BufferedImage img) {
        super(img);
    }

    /**
     * Set the location if it won't be out of bounds. Bounds checking is set
     * via a flag. This will also attempt to set the location as close as
     * possible.
     *
     * @return Returns false if location cannot be set in bounds. Returns true
     *         otherwise.
     */
    public void setLocation(int x, int y) {
        super.setLocation(x, y);
    }

    /**
     * Sets velocityX.
     *
     * @param vlX The value to set velocityX.
     */
    public void setVelocityX(int vlX) {
        mVelocityX = vlX;
    }

    /**
     * Sets velocityY.
     *
     * @param vlY The value to set velocityY.
     */
    public void setVelocityY(int vlY) {
        mVelocityY = vlY;
    }

    /**
     * Gets velocityX.
     *
     * @return The X velocity of the entity.
     */
    public int getVelocityX() {
        return mVelocityX;
    }

    /**
     * Gets velocityY.
     *
     * @return The Y velocity of the entity.
     */
    public int getVelocityY() {
        return mVelocityY;
    }

    /**
     * Gets the internal boundingBox location X.
     *
     * @return boundingBox.getX()
     */
    public int getBoundingBoxX() {
        return (int) mBounds.getX();
    }

    /**
     * Gets the internal boundingBox location Y.
     *
     * @return boundingBox.getY()
     */
    public int getBoundingBoxY() {
        return (int) mBounds.getY();
    }

    /**
     * Gets the internal boundingBox width.
     *
     * @return boundingBox.getWidth()
     */
    public int getBoundingBoxWidth() {
        return (int) mBounds.getWidth();
    }

    /**
     * Gets the internal boundingBox height.
     *
     * @return boundingBox.getHeight()
     */
    public int getBoundingBoxHeight() {
        return (int) mBounds.getHeight();
    }

    /**
     * Determines if the ShipEntity is out of bounds at the current location.
     *
     * @return Whether the ShipEntity is out of bounds.
     */
    protected boolean isOutOfBounds() {
        int r = mImageX + mImageW;
        int b = mImageY + mImageH;

        if (mImageX < (int) mBounds.getX()) {
            return true;
        }
        if (mImageY < (int) mBounds.getY()) {
            return true;
        }
        if (r > ((int) mBounds.getX() + (int) mBounds.getWidth())) {
            return true;
        }
        if (b > ((int) mBounds.getY() + (int) mBounds.getHeight())) {
            return true;
        }

        return false;
    }

    /**
     * Determines if the ShipEntity would be out of bounds at the coordinates
     * given.
     *
     * @param x The x coordinate.
     * @param y The y coordinate.
     * @return Whether the ShipEntity would be out of bounds.
     */
    protected boolean isOutOfBounds(int x, int y) {
        int r = x + mImageW;
        int b = y + mImageH;

        if (x < (int) mBounds.getX()) {
            return true;
        }
        if (y < (int) mBounds.getY()) {
            return true;
        }
        if (r > ((int) mBounds.getX() + (int) mBounds.getWidth())) {
            return true;
        }
        if (b > ((int) mBounds.getY() + (int) mBounds.getHeight())) {
            return true;
        }

        return false;
    }

    /**
     * Finds out if this instance intersects with another instance of Entity.
     *
     * @param e The instance of Entity to compare.
     * @return Boolean value indicating if a collision occurred.
     */
    public boolean intersectsWith(Entity e) {
        int b1 = mImageX + mImageH;
        int b2 = e.getX() + e.getHeight();
        int r1 = mImageY + mImageW;
        int r2 = e.getY() + e.getWidth();

        // eliminate the possibility of non-collision first
        if (b1 < e.getY())
            return (false);
        if (mImageY > b2)
            return (false);
        if (r1 < e.getX())
            return (false);
        if (mImageX > r2)
            return (false);

        return true;
    }

    /**
     * * Finds out if this instance intersects with a Rectangle.
     *
     * @param rct
     * @return Boolean value indicating if a collision occurred.
     */
    public boolean intersectsWith(Rectangle rct) {
        int b1 = mImageX + mImageH;
        int b2 = (int) (rct.getX() + rct.getHeight());
        int r1 = mImageY + mImageW;
        int r2 = (int) (rct.getY() + rct.getWidth());

        // eliminate the possibility of non-collision first
        if (b1 < rct.getY())
            return (false);
        if (mImageY > b2)
            return (false);
        if (r1 < rct.getX())
            return (false);
        if (mImageX > r2)
            return (false);

        return true;
    }

    /**
     * Draws the Entity.
     *
     * @param g The graphics context to load from.
     */
    public void draw(Graphics2D g) {
        try {
            super.draw(g);
        } catch (ImageNotLoadedException e) {
            e.printStackTrace();
        }
    }
}
